package org.fujene.structure;

import java.util.ArrayList;

public class ContentInfo{
	private String[] contentNames;
	private String[] appendixNames;
	private int[][] graph;

	public ContentInfo(String[] contentName, String[] appendixName){
		this.contentNames = contentName;
		this.appendixNames = appendixName;
		if(appendixName.length != 0) graph = new int[contentName.length][];
	}

	// 紐付けを接続
	public void connectGraph(int contentIndex, int[] appendixVector){
		if(contentIndex < contentNames.length) graph[contentIndex] = appendixVector;
	}

	public String getContentName(int index){
		if(index < contentNames.length)
			return contentNames[index];
		else return null;
	}

	public int getContentIndex(String str){
		for(int i = 0; i < contentNames.length; i++){
			if(contentNames[i].equalsIgnoreCase(str)) return i;
		}

		throw new ArrayIndexOutOfBoundsException("No such content type: " + str);
	}

	public String getAppendixName(int index){
		if(index < appendixNames.length)
			return appendixNames[index];
		else return null;
	}

	public int getAppendixIndex(String str){
		for(int i = 0; i < appendixNames.length; i++){
			if(appendixNames[i].equalsIgnoreCase(str)) return i;
		}

		throw new ArrayIndexOutOfBoundsException("No such appendix type: " + str);
	}

	public int getConnectionNum(int index){
		if(graph == null || index >= contentNames.length)
			return 0;
		else if(graph.length != 0)
			return graph[index].length;
		else return 0;
	}

	// 最適化
	public void optimize(){
		if(graph == null) return;
		int[] filled = new int[contentNames.length];

		for(int i = 0; i < graph.length; i++){
			if(graph[i] != null){
				for(int j = 0; j < graph[i].length; j++){
					filled[graph[i][j]] = 1;
				}
			}
		}

		ArrayList<String> newapp = new ArrayList<String>();
		ArrayList<Integer> renumber = new ArrayList<Integer>();
		for(int i = 0; i < filled.length; i++){
			if(filled[i] == 1){
				// つながってる！
				newapp.add(appendixNames[i]);
				renumber.add(Integer.valueOf(i));
			}
		}

		// いらない追加情報は消す
		appendixNames = newapp.toArray(new String[newapp.size()]);

		// リナンバリング
		for(int i = 0; i < graph.length; i++){
			if(graph[i] != null){
				for(int j = 0; j < graph[i].length; j++)
					graph[i][j] = renumber.indexOf(Integer.valueOf(graph[i][j]));
			}
		}
	}

	public int getContentNum(){
		return contentNames.length;
	}

	public int getAppendixNum(){
		return appendixNames.length;
	}

	public byte[] getConnection(){
		ArrayList<Byte> retb = new ArrayList<Byte>();
		if(graph == null)
			retb.add((byte)0);
		else{
			retb.add((byte)graph.length);
			for(int i = 0; i < graph.length; i++){
				retb.add((byte)graph[i].length);
				for(int j = 0; j < graph[i].length; j++){
					retb.add(Byte.valueOf((byte)graph[i][j]));
				}
			}
		}
		byte[] newb = new byte[retb.size()];
		for(int i = 0; i < retb.size(); i++){
			newb[i] = retb.get(i).byteValue();
		}

		return newb;
	}

	public void setConnection(byte[] b){
		int counter = 1;
		graph = new int[b[0]][];
		for(int i = 0; i < b[0]; i++){
			graph[i] = new int[b[counter++]];
			for(int j = 0; j < graph[i].length; j++)
				graph[i][j] = b[counter++];
		}
	}

	public LookupPointer[] constructIndex(LookupPointer[] appPtrs, int contentIndex){
		if(appPtrs.length > 0){
			LookupPointer[] retPtrs = new LookupPointer[graph[contentIndex].length];

			for(int i = 0; i < retPtrs.length; i++){
				retPtrs[i] = appPtrs[graph[contentIndex][i]];
			}

			return retPtrs;
		}else return null;
	}
}
